<!DOCTYPE html>
<html id="docs" lang="en" class="">
	<head>
	<meta charset="utf-8">
<title>Connecting Applications with Services - Kubernetes</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" type="image/png" href="../../../../images/favicon.png">
<link rel="stylesheet" type="text/css" href="../../../../css/base_fonts.css">
<link rel="stylesheet" type="text/css" href="../../../../css/styles.css">
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
<link rel="stylesheet" type="text/css" href="../../../../css/callouts.css">
<link rel="stylesheet" type="text/css" href="../../../../css/custom-jekyll/tags.css">




<meta name="description" content="Connecting Applications with Services" />
<meta property="og:description" content="Connecting Applications with Services" />

<meta property="og:url" content="https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/" />
<meta property="og:title" content="Connecting Applications with Services - Kubernetes" />

<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script
src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
<script src="../../../../js/script.js"></script>
<script src="../../../../js/custom-jekyll/tags.js"></script>


	</head>
	<body>
		<div id="cellophane" onclick="kub.toggleMenu()"></div>

<header>
    <a href="../../../../index.html" class="logo"></a>

    <div class="nav-buttons" data-auto-burger="primary">
        <ul class="global-nav">
            
            
            <li><a href="../../../home.1">Documentation</a></li>
            
            <li><a href="../../../../blog/index.html">Blog</a></li>
            
            <li><a href="../../../../partners/index.html">Partners</a></li>
            
            <li><a href="../../../../community/index.html">Community</a></li>
            
            <li><a href="../../../../case-studies/index.html">Case Studies</a></li>
            
            
             <li>
                <a href="../connect-applications-service.1#">
                    English <span class="ui-icon ui-icon-carat-1-s"></span>
                </a>
                <ul>
                
                    <li><a href="../../../../zh/index.html">中文 Chinese</a></li>
                
                    <li><a href="../../../../ko/index.html">한국어 Korean</a></li>
                
                </ul>
            </li>
         
            <li>
                <a href="../connect-applications-service.1#">
                    v1.11 <span class="ui-icon ui-icon-carat-1-s"></span>
                </a>
                <ul>
                
                    <li><a href="https://kubernetes.io">v1.12</a></li>
                
                    <li><a href="../../../../index.html">v1.11</a></li>
                
                    <li><a href="https://v1-10.docs.kubernetes.io">v1.10</a></li>
                
                    <li><a href="https://v1-9.docs.kubernetes.io">v1.9</a></li>
                
                </ul>
            </li>
        </ul>
        
        <a href="../../../tutorials/kubernetes-basics/index.html" class="button" id="tryKubernetes" data-auto-burger-exclude>Try Kubernetes</a>
        <button id="hamburger" onclick="kub.toggleMenu()" data-auto-burger-exclude><div></div></button>
    </div>

    <nav id="mainNav">
        <main data-auto-burger="primary">
        <div class="nav-box">
            <h3><a href="../../../tutorials/stateless-application/hello-minikube/index.html">Get Started</a></h3>
            <p>Ready to get your hands dirty? Build a simple Kubernetes cluster that runs "Hello World" for Node.js.</p>
        </div>
        <div class="nav-box">
            <h3><a href="../../../home.1">Documentation</a></h3>
            <p>Learn how to use Kubernetes with the use of walkthroughs, samples, and reference documentation. You can even <a href="../../../../editdocs/index.html" data-auto-burger-exclude>help contribute to the docs</a>!</p>
        </div>
        <div class="nav-box">
            <h3><a href="../../../../community/index.html">Community</a></h3>
            <p>If you need help, you can connect with other Kubernetes users and the Kubernetes authors, attend community events, and watch video presentations from around the web.</p>
        </div>
        <div class="nav-box">
            <h3><a href="../../../../blog/index.html">Blog</a></h3>
            <p>Read the latest news for Kubernetes and the containers space in general, and get technical how-tos hot off the presses.</p>
        </div>
        </main>
        <main data-auto-burger="primary">
        <div class="left">
            <h5 class="github-invite">Interested in hacking on the core Kubernetes code base?</h5>
            <a href="https://github.com/kubernetes/kubernetes" class="button" data-auto-burger-exclude>View On Github</a>
        </div>

        <div class="right">
            <h5 class="github-invite">Explore the community</h5>
            <div class="social">
                <a href="https://twitter.com/kubernetesio" class="twitter"><span>Twitter</span></a>
                <a href="https://github.com/kubernetes/kubernetes" class="github"><span>Github</span></a>
                <a href="http://slack.k8s.io/" class="slack"><span>Slack</span></a>
                <a href="http://stackoverflow.com/questions/tagged/kubernetes" class="stack-overflow"><span>Stack Overflow</span></a>
                <a href="https://discuss.kubernetes.io" class="mailing-list"><span>Forum</span></a>
                <a href="https://calendar.google.com/calendar/embed?src=nt2tcnbtbied3l6gi2h29slvc0%40group.calendar.google.com" class="calendar"><span>Events Calendar</span></a>
            </div>
        </div>
        <div class="clear" style="clear: both"></div>
        </main>
    </nav>
</header>

		
		
		<section id="hero" class="light-text no-sub">
			









<h1>Concepts</h1>
<h5></h5>








<div id="vendorStrip" class="light-text">
	<ul>
		
		
		<li><a href="../../../home.1">DOCUMENTATION</a></li>
		
		
		<li><a href="../../../setup/index.html">SETUP</a></li>
		
		
		<li><a href="../../index.html" class="YAH">CONCEPTS</a></li>
		
		
		<li><a href="../../../tasks/index.html">TASKS</a></li>
		
		
		<li><a href="../../../tutorials/index.html">TUTORIALS</a></li>
		
		
		<li><a href="../../../reference.1">REFERENCE</a></li>
		
	</ul>
	<div id="searchBox">
		<input type="text" id="search" placeholder="Search" onkeydown="if (event.keyCode==13) window.location.replace('/docs/search/?q=' + this.value)" autofocus="autofocus">
	</div>
</div>

		</section>
		
		
<section id="deprecationWarning">
  <main>
    <div class="content deprecation-warning">
      <h3>
        Documentation for Kubernetes v1.11 is no longer actively maintained. The version you are currently viewing is a static snapshot.
        For up-to-date documentation, see the <a href="https://kubernetes.io/docs/home/">latest</a> version.
      </h3>
    </div>
  </main>
</section>


		<section id="encyclopedia">
			
<div id="docsToc">
     <div class="pi-accordion">
    	
        
        
        
        
        
         
             
                 
             
         
             
                 
             
         
             
                 
                          
                          
                 
             
         
             
         
             
         
             
         
             
         
             
         
         
        
        <a class="item" data-title="Concepts" href="../../index.html"></a>

	
	
		
		
	<div class="item" data-title="Overview">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="What is Kubernetes?" href="../../overview/index.html"></a>

		
	
		
		
<a class="item" data-title="Kubernetes Components" href="../../overview/components.1"></a>

		
	
		
		
<a class="item" data-title="The Kubernetes API" href="../../overview/kubernetes-api/index.html"></a>

		
	
		
		
	<div class="item" data-title="Working with Kubernetes Objects">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Understanding Kubernetes Objects" href="../../overview/working-with-objects/kubernetes-objects.1"></a>

		
	
		
		
<a class="item" data-title="Names" href="../../../user-guide/identifiers"></a>

		
	
		
		
<a class="item" data-title="Namespaces" href="../../overview/working-with-objects/namespaces.1"></a>

		
	
		
		
<a class="item" data-title="Labels and Selectors" href="../../../user-guide/labels"></a>

		
	
		
		
<a class="item" data-title="Annotations" href="../../overview/working-with-objects/annotations.1"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Object Management Using kubectl">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Kubernetes Object Management" href="../../../tutorials/object-management-kubectl/object-management/index.html"></a>

		
	
		
		
<a class="item" data-title="Managing Kubernetes Objects Using Imperative Commands" href="../../../tutorials/object-management-kubectl/imperative-object-management-command/index.html"></a>

		
	
		
		
<a class="item" data-title="Imperative Management of Kubernetes Objects Using Configuration Files" href="../../../tutorials/object-management-kubectl/imperative-object-management-configuration/index.html"></a>

		
	
		
		
<a class="item" data-title="Declarative Management of Kubernetes Objects Using Configuration Files" href="../../../tutorials/object-management-kubectl/declarative-object-management-configuration/index.html"></a>

		
	

		</div>
	</div>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Compute, Storage, and Networking Extensions">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Cluster Administration Overview" href="../../cluster-administration/cluster-administration-overview/index.html"></a>

		
	
		
		
<a class="item" data-title="Certificates" href="../../cluster-administration/certificates/index.html"></a>

		
	
		
		
<a class="item" data-title="Cloud Providers" href="../../cluster-administration/cloud-providers/index.html"></a>

		
	
		
		
<a class="item" data-title="Managing Resources" href="../../cluster-administration/manage-deployment/index.html"></a>

		
	
		
		
<a class="item" data-title="Cluster Networking" href="../../../admin/networking"></a>

		
	
		
		
<a class="item" data-title="Logging Architecture" href="../../cluster-administration/logging.1"></a>

		
	
		
		
<a class="item" data-title="Configuring kubelet Garbage Collection" href="../../cluster-administration/kubelet-garbage-collection/index.html"></a>

		
	
		
		
<a class="item" data-title="Federation" href="../../cluster-administration/federation/index.html"></a>

		
	
		
		
<a class="item" data-title="Proxies in Kubernetes" href="../../cluster-administration/proxies/index.html"></a>

		
	
		
		
<a class="item" data-title="Controller manager metrics" href="../../cluster-administration/controller-metrics/index.html"></a>

		
	
		
		
<a class="item" data-title="Installing Addons" href="../../cluster-administration/addons/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Kubernetes Architecture">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Nodes" href="../../../admin/node.1"></a>

		
	
		
		
<a class="item" data-title="Master-Node communication" href="../../architecture/master-node-communication/index.html"></a>

		
	
		
		
<a class="item" data-title="Concepts Underlying the Cloud Controller Manager" href="../../architecture/cloud-controller/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Extending Kubernetes">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Extending your Kubernetes Cluster" href="../../overview/extending/index.html"></a>

		
	
		
		
	<div class="item" data-title="Extending the Kubernetes API">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Extending the Kubernetes API with the aggregation layer" href="../../api-extension/apiserver-aggregation.1"></a>

		
	
		
		
<a class="item" data-title="Custom Resources" href="../../api-extension/custom-resources/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Compute, Storage, and Networking Extensions">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Network Plugins" href="../../../admin/network-plugins/index.html"></a>

		
	
		
		
<a class="item" data-title="Device Plugins" href="../../cluster-administration/device-plugins.1"></a>

		
	

		</div>
	</div>

		
	
		
		
<a class="item" data-title="Service Catalog" href="../../service-catalog/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Containers">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Images" href="../../containers/images/index.html"></a>

		
	
		
		
<a class="item" data-title="Container Environment Variables" href="../../containers/container-environment-variables/index.html"></a>

		
	
		
		
<a class="item" data-title="Container Lifecycle Hooks" href="../../containers/container-lifecycle-hooks/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Workloads">
		<div class="container">
		
		
	
	
		
		
	<div class="item" data-title="Pods">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Pod Overview" href="../../workloads/pods/pod-overview/index.html"></a>

		
	
		
		
<a class="item" data-title="Pods" href="../../../user-guide/pods/index.html"></a>

		
	
		
		
<a class="item" data-title="Pod Lifecycle" href="../../../user-guide/pod-states/index.html"></a>

		
	
		
		
<a class="item" data-title="Init Containers" href="../../abstractions/init-containers/index.html"></a>

		
	
		
		
<a class="item" data-title="Pod Preset" href="../../workloads/pods/podpreset/index.html"></a>

		
	
		
		
<a class="item" data-title="Disruptions" href="../../workloads/pods/disruptions/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Controllers">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="ReplicaSet" href="../../workloads/controllers/replicaset/index.html"></a>

		
	
		
		
<a class="item" data-title="ReplicationController" href="../../../user-guide/replication-controller/index.html"></a>

		
	
		
		
<a class="item" data-title="Deployments" href="../../workloads/controllers/deployment/index.html"></a>

		
	
		
		
<a class="item" data-title="StatefulSets" href="../../workloads/controllers/statefulset.md"></a>

		
	
		
		
<a class="item" data-title="DaemonSet" href="../../workloads/controllers/daemonset.1"></a>

		
	
		
		
<a class="item" data-title="Garbage Collection" href="../../workloads/controllers/garbage-collection/index.html"></a>

		
	
		
		
<a class="item" data-title="Jobs - Run to Completion" href="../../workloads/controllers/jobs-run-to-completion.1"></a>

		
	
		
		
<a class="item" data-title="CronJob" href="../../workloads/controllers/cron-jobs.1"></a>

		
	

		</div>
	</div>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Configuration">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Configuration Best Practices" href="../../configuration/overview/index.html"></a>

		
	
		
		
<a class="item" data-title="Managing Compute Resources for Containers" href="../../../user-guide/compute-resources/index.html"></a>

		
	
		
		
<a class="item" data-title="Assigning Pods to Nodes" href="../../../user-guide/node-selection/index.html"></a>

		
	
		
		
<a class="item" data-title="Taints and Tolerations" href="../../configuration/taint-and-toleration.1"></a>

		
	
		
		
<a class="item" data-title="Secrets" href="../../../user-guide/secrets.1"></a>

		
	
		
		
<a class="item" data-title="Organizing Cluster Access Using kubeconfig Files" href="../../configuration/organize-cluster-access-kubeconfig/index.html"></a>

		
	
		
		
<a class="item" data-title="Pod Priority and Preemption" href="../../configuration/pod-priority-preemption/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Services, Load Balancing, and Networking">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Services" href="../../../user-guide/services"></a>

		
	
		
		
<a class="item" data-title="DNS for Services and Pods" href="../dns-pod-service/index.html"></a>

		
	
		
		
<a class="item" data-title="Connecting Applications with Services" href="../connect-applications-service.1"></a>

		
	
		
		
<a class="item" data-title="Ingress" href="../ingress/index.html"></a>

		
	
		
		
<a class="item" data-title="Network Policies" href="../networkpolicies/index.html"></a>

		
	
		
		
<a class="item" data-title="Adding entries to Pod /etc/hosts with HostAliases" href="../add-entries-to-pod-etc-hosts-with-host-aliases/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Storage">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Volumes" href="../../storage/volumes.1"></a>

		
	
		
		
<a class="item" data-title="Persistent Volumes" href="../../../user-guide/persistent-volumes/index.html"></a>

		
	
		
		
<a class="item" data-title="Storage Classes" href="../../storage/storage-classes.1"></a>

		
	
		
		
<a class="item" data-title="Dynamic Volume Provisioning" href="../../storage/dynamic-provisioning/index.html"></a>

		
	
		
		
<a class="item" data-title="Node-specific Volume Limits" href="../../storage/storage-limits/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Policies">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Resource Quotas" href="../../policy/resource-quotas/index.html"></a>

		
	
		
		
<a class="item" data-title="Pod Security Policies" href="../../../user-guide/pod-security-policy"></a>

		
	

		</div>
	</div>

		
	






     </div> 
    <button class="push-menu-close-button" onclick="kub.toggleToc()"></button>
</div> 

			<div id="docsContent">
				
<p><a href="../../../editdocs#docs/concepts/services-networking/connect-applications-service.md" id="editPageButton">Edit This Page</a></p>

<h1>Connecting Applications with Services</h1>



<h2 id="the-kubernetes-model-for-connecting-containers">The Kubernetes model for connecting containers</h2>

<p>Now that you have a continuously running, replicated application you can expose it on a network. Before discussing the Kubernetes approach to networking, it is worthwhile to contrast it with the &ldquo;normal&rdquo; way networking works with Docker.</p>

<p>By default, Docker uses host-private networking, so containers can talk to other containers only if they are on the same machine. In order for Docker containers to communicate across nodes, there must be allocated ports on the machine’s own IP address, which are then forwarded or proxied to the containers. This obviously means that containers must either coordinate which ports they use very carefully or ports must be allocated dynamically.</p>

<p>Coordinating ports across multiple developers is very difficult to do at scale and exposes users to cluster-level issues outside of their control. Kubernetes assumes that pods can communicate with other pods, regardless of which host they land on. We give every pod its own cluster-private-IP address so you do not need to explicitly create links between pods or mapping container ports to host ports. This means that containers within a Pod can all reach each other&rsquo;s ports on localhost, and all pods in a cluster can see each other without NAT. The rest of this document will elaborate on how you can run reliable services on such a networking model.</p>

<p>This guide uses a simple nginx server to demonstrate proof of concept. The same principles are embodied in a more complete <a href="https://kubernetes.io/blog/2015/07/strong-simple-ssl-for-kubernetes" target="_blank">Jenkins CI application</a>.</p>









<ul id="markdown-toc">










<li><a href="../connect-applications-service.1#exposing-pods-to-the-cluster">Exposing pods to the cluster</a></li>




<li><a href="../connect-applications-service.1#creating-a-service">Creating a Service</a></li>




<li><a href="../connect-applications-service.1#accessing-the-service">Accessing the Service</a></li>




<li><a href="../connect-applications-service.1#securing-the-service">Securing the Service</a></li>




<li><a href="../connect-applications-service.1#exposing-the-service">Exposing the Service</a></li>




















<li><a href="../connect-applications-service.1#what-s-next">What's next</a></li>



</ul>


<h2 id="exposing-pods-to-the-cluster">Exposing pods to the cluster</h2>

<p>We did this in a previous example, but let&rsquo;s do it once again and focus on the networking perspective. Create an nginx pod, and note that it has a container port specification:</p>

<table class="includecode" id="run-my-nginx-yaml">
    <thead>
        <tr>
            <th>
                <a href="https://github.com/kubernetes/website/blob/master/content/en/docs/concepts/services-networking/run-my-nginx.yaml" download="run-my-nginx.yaml">
                    <code>run-my-nginx.yaml docs/concepts/services-networking</code>
                </a>
                <img src="../../../../images/copycode.svg" style="max-height:24px" onclick="copyCode('run-my-nginx-yaml')" title="Copy run-my-nginx.yaml to clipboard">
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml">apiVersion:<span style="color:#bbb"> </span>apps/v1<span style="color:#bbb">
</span><span style="color:#bbb"></span>kind:<span style="color:#bbb"> </span>Deployment<span style="color:#bbb">
</span><span style="color:#bbb"></span>metadata:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>name:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb"></span>spec:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>selector:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>matchLabels:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>run:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb">  </span>replicas:<span style="color:#bbb"> </span><span style="color:#666">2</span><span style="color:#bbb">
</span><span style="color:#bbb">  </span>template:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>metadata:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>labels:<span style="color:#bbb">
</span><span style="color:#bbb">        </span>run:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb">    </span>spec:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>containers:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>-<span style="color:#bbb"> </span>name:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb">        </span>image:<span style="color:#bbb"> </span>nginx<span style="color:#bbb">
</span><span style="color:#bbb">        </span>ports:<span style="color:#bbb">
</span><span style="color:#bbb">        </span>-<span style="color:#bbb"> </span>containerPort:<span style="color:#bbb"> </span><span style="color:#666">80</span><span style="color:#bbb">
</span><span style="color:#bbb">
</span><span style="color:#bbb"></span></code></pre></div>  </td>
        </tr>
    </tbody>
</table>

<p>This makes it accessible from any node in your cluster. Check the nodes the pod is running on:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl create -f ./run-my-nginx.yaml
$ kubectl get pods -l <span style="color:#b8860b">run</span><span style="color:#666">=</span>my-nginx -o wide
NAME                        READY     STATUS    RESTARTS   AGE       IP            NODE
my-nginx-3800858182-jr4a2   <span style="color:#666">1</span>/1       Running   <span style="color:#666">0</span>          13s       <span style="color:#666">10</span>.244.3.4    kubernetes-minion-905m
my-nginx-3800858182-kna2y   <span style="color:#666">1</span>/1       Running   <span style="color:#666">0</span>          13s       <span style="color:#666">10</span>.244.2.5    kubernetes-minion-ljyd</code></pre></div>
<p>Check your pods&rsquo; IPs:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl get pods -l <span style="color:#b8860b">run</span><span style="color:#666">=</span>my-nginx -o yaml | grep podIP
    podIP: <span style="color:#666">10</span>.244.3.4
    podIP: <span style="color:#666">10</span>.244.2.5</code></pre></div>
<p>You should be able to ssh into any node in your cluster and curl both IPs. Note that the containers are <em>not</em> using port 80 on the node, nor are there any special NAT rules to route traffic to the pod. This means you can run multiple nginx pods on the same node all using the same containerPort and access them from any other pod or node in your cluster using IP. Like Docker, ports can still be published to the host node&rsquo;s interfaces, but the need for this is radically diminished because of the networking model.</p>

<p>You can read more about <a href="../../../admin/networking#how-to-achieve-this">how we achieve this</a> if you&rsquo;re curious.</p>

<h2 id="creating-a-service">Creating a Service</h2>

<p>So we have pods running nginx in a flat, cluster wide, address space. In theory, you could talk to these pods directly, but what happens when a node dies? The pods die with it, and the Deployment will create new ones, with different IPs. This is the problem a Service solves.</p>

<p>A Kubernetes Service is an abstraction which defines a logical set of Pods running somewhere in your cluster, that all provide the same functionality. When created, each Service is assigned a unique IP address (also called clusterIP). This address is tied to the lifespan of the Service, and will not change while the Service is alive. Pods can be configured to talk to the Service, and know that communication to the Service will be automatically load-balanced out to some pod that is a member of the Service.</p>

<p>You can create a Service for your 2 nginx replicas with <code>kubectl expose</code>:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl expose deployment/my-nginx
service <span style="color:#b44">&#34;my-nginx&#34;</span> exposed</code></pre></div>
<p>This is equivalent to <code>kubectl create -f</code> the following yaml:</p>

<table class="includecode" id="nginx-svc-yaml">
    <thead>
        <tr>
            <th>
                <a href="https://github.com/kubernetes/website/blob/master/content/en/docs/concepts/services-networking/nginx-svc.yaml" download="nginx-svc.yaml">
                    <code>nginx-svc.yaml docs/concepts/services-networking</code>
                </a>
                <img src="../../../../images/copycode.svg" style="max-height:24px" onclick="copyCode('nginx-svc-yaml')" title="Copy nginx-svc.yaml to clipboard">
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml">apiVersion:<span style="color:#bbb"> </span>v1<span style="color:#bbb">
</span><span style="color:#bbb"></span>kind:<span style="color:#bbb"> </span>Service<span style="color:#bbb">
</span><span style="color:#bbb"></span>metadata:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>name:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb">  </span>labels:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>run:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb"></span>spec:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>ports:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>-<span style="color:#bbb"> </span>port:<span style="color:#bbb"> </span><span style="color:#666">80</span><span style="color:#bbb">
</span><span style="color:#bbb">    </span>protocol:<span style="color:#bbb"> </span>TCP<span style="color:#bbb">
</span><span style="color:#bbb">  </span>selector:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>run:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb"></span></code></pre></div>  </td>
        </tr>
    </tbody>
</table>

<p>This specification will create a Service which targets TCP port 80 on any Pod with the <code>run: my-nginx</code> label, and expose it on an abstracted Service port (<code>targetPort</code>: is the port the container accepts traffic on, <code>port</code>: is the abstracted Service port, which can be any port other pods use to access the Service). View <a href="../../../reference/generated/kubernetes-api/v1.11/index.html#service-v1-core">service API object</a> to see the list of supported fields in service definition.
Check your Service:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl get svc my-nginx
NAME       CLUSTER-IP     EXTERNAL-IP   PORT<span style="color:#666">(</span>S<span style="color:#666">)</span>   AGE
my-nginx   <span style="color:#666">10</span>.0.162.149   &lt;none&gt;        <span style="color:#666">80</span>/TCP    21s</code></pre></div>
<p>As mentioned previously, a Service is backed by a group of pods. These pods are exposed through <code>endpoints</code>. The Service&rsquo;s selector will be evaluated continuously and the results will be POSTed to an Endpoints object also named <code>my-nginx</code>. When a pod dies, it is automatically removed from the endpoints, and new pods matching the Service&rsquo;s selector will automatically get added to the endpoints. Check the endpoints, and note that the IPs are the same as the pods created in the first step:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl describe svc my-nginx
Name:                my-nginx
Namespace:           default
Labels:              <span style="color:#b8860b">run</span><span style="color:#666">=</span>my-nginx
Annotations:         &lt;none&gt;
Selector:            <span style="color:#b8860b">run</span><span style="color:#666">=</span>my-nginx
Type:                ClusterIP
IP:                  <span style="color:#666">10</span>.0.162.149
Port:                &lt;unset&gt; <span style="color:#666">80</span>/TCP
Endpoints:           <span style="color:#666">10</span>.244.2.5:80,10.244.3.4:80
Session Affinity:    None
Events:              &lt;none&gt;

$ kubectl get ep my-nginx
NAME       ENDPOINTS                     AGE
my-nginx   <span style="color:#666">10</span>.244.2.5:80,10.244.3.4:80   1m</code></pre></div>
<p>You should now be able to curl the nginx Service on <code>&lt;CLUSTER-IP&gt;:&lt;PORT&gt;</code> from any node in your cluster. Note that the Service IP is completely virtual, it never hits the wire, if you&rsquo;re curious about how this works you can read more about the <a href="../../../user-guide/services#virtual-ips-and-service-proxies">service proxy</a>.</p>

<h2 id="accessing-the-service">Accessing the Service</h2>

<p>Kubernetes supports 2 primary modes of finding a Service - environment variables and DNS. The former works out of the box while the latter requires the <a href="http://releases.k8s.io/v1.11.3/cluster/addons/dns/kube-dns/README.md" target="_blank">kube-dns cluster addon</a>.</p>

<h3 id="environment-variables">Environment Variables</h3>

<p>When a Pod runs on a Node, the kubelet adds a set of environment variables for each active Service. This introduces an ordering problem. To see why, inspect the environment of your running nginx pods (your pod name will be different):</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl <span style="color:#a2f">exec</span> my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
<span style="color:#b8860b">KUBERNETES_SERVICE_HOST</span><span style="color:#666">=</span><span style="color:#666">10</span>.0.0.1
<span style="color:#b8860b">KUBERNETES_SERVICE_PORT</span><span style="color:#666">=</span><span style="color:#666">443</span>
<span style="color:#b8860b">KUBERNETES_SERVICE_PORT_HTTPS</span><span style="color:#666">=</span><span style="color:#666">443</span></code></pre></div>
<p>Note there&rsquo;s no mention of your Service. This is because you created the replicas before the Service. Another disadvantage of doing this is that the scheduler might put both pods on the same machine, which will take your entire Service down if it dies. We can do this the right way by killing the 2 pods and waiting for the Deployment to recreate them. This time around the Service exists <em>before</em> the replicas. This will give you scheduler-level Service spreading of your pods (provided all your nodes have equal capacity), as well as the right environment variables:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl scale deployment my-nginx --replicas<span style="color:#666">=</span><span style="color:#666">0</span>; kubectl scale deployment my-nginx --replicas<span style="color:#666">=</span><span style="color:#666">2</span>;

$ kubectl get pods -l <span style="color:#b8860b">run</span><span style="color:#666">=</span>my-nginx -o wide
NAME                        READY     STATUS    RESTARTS   AGE     IP            NODE
my-nginx-3800858182-e9ihh   <span style="color:#666">1</span>/1       Running   <span style="color:#666">0</span>          5s      <span style="color:#666">10</span>.244.2.7    kubernetes-minion-ljyd
my-nginx-3800858182-j4rm4   <span style="color:#666">1</span>/1       Running   <span style="color:#666">0</span>          5s      <span style="color:#666">10</span>.244.3.8    kubernetes-minion-905m</code></pre></div>
<p>You may notice that the pods have different names, since they are killed and recreated.</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl <span style="color:#a2f">exec</span> my-nginx-3800858182-e9ihh -- printenv | grep SERVICE
<span style="color:#b8860b">KUBERNETES_SERVICE_PORT</span><span style="color:#666">=</span><span style="color:#666">443</span>
<span style="color:#b8860b">MY_NGINX_SERVICE_HOST</span><span style="color:#666">=</span><span style="color:#666">10</span>.0.162.149
<span style="color:#b8860b">KUBERNETES_SERVICE_HOST</span><span style="color:#666">=</span><span style="color:#666">10</span>.0.0.1
<span style="color:#b8860b">MY_NGINX_SERVICE_PORT</span><span style="color:#666">=</span><span style="color:#666">80</span>
<span style="color:#b8860b">KUBERNETES_SERVICE_PORT_HTTPS</span><span style="color:#666">=</span><span style="color:#666">443</span></code></pre></div>
<h3 id="dns">DNS</h3>

<p>Kubernetes offers a DNS cluster addon Service that automatically assigns dns names to other Services. You can check if it&rsquo;s running on your cluster:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl get services kube-dns --namespace<span style="color:#666">=</span>kube-system
NAME       CLUSTER-IP   EXTERNAL-IP   PORT<span style="color:#666">(</span>S<span style="color:#666">)</span>         AGE
kube-dns   <span style="color:#666">10</span>.0.0.10    &lt;none&gt;        <span style="color:#666">53</span>/UDP,53/TCP   8m</code></pre></div>
<p>If it isn&rsquo;t running, you can <a href="http://releases.k8s.io/v1.11.3/cluster/addons/dns/README.md#how-do-i-configure-it" target="_blank">enable it</a>. The rest of this section will assume you have a Service with a long lived IP (my-nginx), and a dns server that has assigned a name to that IP (the kube-dns cluster addon), so you can talk to the Service from any pod in your cluster using standard methods (e.g. gethostbyname). Let&rsquo;s run another curl application to test this:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl run curl --image<span style="color:#666">=</span>radial/busyboxplus:curl -i --tty
Waiting <span style="color:#a2f;font-weight:bold">for</span> pod default/curl-131556218-9fnch to be running, status is Pending, pod ready: <span style="color:#a2f">false</span>
Hit enter <span style="color:#a2f;font-weight:bold">for</span> <span style="color:#a2f">command</span> prompt</code></pre></div>
<p>Then, hit enter and run <code>nslookup my-nginx</code>:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#666">[</span> root@curl-131556218-9fnch:/ <span style="color:#666">]</span>$ nslookup my-nginx
Server:    <span style="color:#666">10</span>.0.0.10
Address <span style="color:#666">1</span>: <span style="color:#666">10</span>.0.0.10

Name:      my-nginx
Address <span style="color:#666">1</span>: <span style="color:#666">10</span>.0.162.149</code></pre></div>
<h2 id="securing-the-service">Securing the Service</h2>

<p>Till now we have only accessed the nginx server from within the cluster. Before exposing the Service to the internet, you want to make sure the communication channel is secure. For this, you will need:</p>

<ul>
<li>Self signed certificates for https (unless you already have an identity certificate)</li>
<li>An nginx server configured to use the certificates</li>
<li>A <a href="../../../user-guide/secrets.1">secret</a> that makes the certificates accessible to pods</li>
</ul>

<p>You can acquire all these from the <a href="https://github.com/kubernetes/examples/tree/v1.11.3/staging/https-nginx/" target="_blank">nginx https example</a>. This requires having go and make tools installed. If you don&rsquo;t want to install those, then follow the  manual steps later. In short:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ make keys secret <span style="color:#b8860b">KEY</span><span style="color:#666">=</span>/tmp/nginx.key <span style="color:#b8860b">CERT</span><span style="color:#666">=</span>/tmp/nginx.crt <span style="color:#b8860b">SECRET</span><span style="color:#666">=</span>/tmp/secret.json
$ kubectl create -f /tmp/secret.json
secret <span style="color:#b44">&#34;nginxsecret&#34;</span> created
$ kubectl get secrets
NAME                  TYPE                                  DATA      AGE
default-token-il9rc   kubernetes.io/service-account-token   <span style="color:#666">1</span>         1d
nginxsecret           Opaque                                <span style="color:#666">2</span>         1m</code></pre></div>
<p>Following are the manual steps to follow in case you run into problems running make (on windows for example):</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#080;font-style:italic">#create a public private key pair
</span><span style="color:#080;font-style:italic"></span>openssl req -x509 -nodes -days <span style="color:#666">365</span> -newkey rsa:2048 -keyout /d/tmp/nginx.key -out /d/tmp/nginx.crt -subj <span style="color:#b44">&#34;/CN=my-nginx/O=my-nginx&#34;</span>
<span style="color:#080;font-style:italic">#convert the keys to base64 encoding
</span><span style="color:#080;font-style:italic"></span>cat /d/tmp/nginx.crt | base64
cat /d/tmp/nginx.key | base64</code></pre></div>
<p>Use the output from the previous commands to create a yaml file as follows. The base64 encoded value should all be on a single line.</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml">apiVersion:<span style="color:#bbb"> </span><span style="color:#b44">&#34;v1&#34;</span><span style="color:#bbb">
</span><span style="color:#bbb"></span>kind:<span style="color:#bbb"> </span><span style="color:#b44">&#34;Secret&#34;</span><span style="color:#bbb">
</span><span style="color:#bbb"></span>metadata:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>name:<span style="color:#bbb"> </span><span style="color:#b44">&#34;nginxsecret&#34;</span><span style="color:#bbb">
</span><span style="color:#bbb">  </span>namespace:<span style="color:#bbb"> </span><span style="color:#b44">&#34;default&#34;</span><span style="color:#bbb">
</span><span style="color:#bbb"></span>data:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>nginx.crt:<span style="color:#bbb"> </span><span style="color:#b44">&#34;LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURIekNDQWdlZ0F3SUJBZ0lKQUp5M3lQK0pzMlpJTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ1l4RVRBUEJnTlYKQkFNVENHNW5hVzU0YzNaak1SRXdEd1lEVlFRS0V3aHVaMmx1ZUhOMll6QWVGdzB4TnpFd01qWXdOekEzTVRKYQpGdzB4T0RFd01qWXdOekEzTVRKYU1DWXhFVEFQQmdOVkJBTVRDRzVuYVc1NGMzWmpNUkV3RHdZRFZRUUtFd2h1CloybHVlSE4yWXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSjFxSU1SOVdWM0IKMlZIQlRMRmtobDRONXljMEJxYUhIQktMSnJMcy8vdzZhU3hRS29GbHlJSU94NGUrMlN5ajBFcndCLzlYTnBwbQppeW1CL3JkRldkOXg5UWhBQUxCZkVaTmNiV3NsTVFVcnhBZW50VWt1dk1vLzgvMHRpbGhjc3paenJEYVJ4NEo5Ci82UVRtVVI3a0ZTWUpOWTVQZkR3cGc3dlVvaDZmZ1Voam92VG42eHNVR0M2QURVODBpNXFlZWhNeVI1N2lmU2YKNHZpaXdIY3hnL3lZR1JBRS9mRTRqakxCdmdONjc2SU90S01rZXV3R0ljNDFhd05tNnNTSzRqYUNGeGpYSnZaZQp2by9kTlEybHhHWCtKT2l3SEhXbXNhdGp4WTRaNVk3R1ZoK0QrWnYvcW1mMFgvbVY0Rmo1NzV3ajFMWVBocWtsCmdhSXZYRyt4U1FVQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjcKTUI4R0ExVWRJd1FZTUJhQUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjdNQXdHQTFVZEV3UUZNQU1CQWY4dwpEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRVhTMW9FU0lFaXdyMDhWcVA0K2NwTHI3TW5FMTducDBvMm14alFvCjRGb0RvRjdRZnZqeE04Tzd2TjB0clcxb2pGSW0vWDE4ZnZaL3k4ZzVaWG40Vm8zc3hKVmRBcStNZC9jTStzUGEKNmJjTkNUekZqeFpUV0UrKzE5NS9zb2dmOUZ3VDVDK3U2Q3B5N0M3MTZvUXRUakViV05VdEt4cXI0Nk1OZWNCMApwRFhWZmdWQTRadkR4NFo3S2RiZDY5eXM3OVFHYmg5ZW1PZ05NZFlsSUswSGt0ejF5WU4vbVpmK3FqTkJqbWZjCkNnMnlwbGQ0Wi8rUUNQZjl3SkoybFIrY2FnT0R4elBWcGxNSEcybzgvTHFDdnh6elZPUDUxeXdLZEtxaUMwSVEKQ0I5T2wwWW5scE9UNEh1b2hSUzBPOStlMm9KdFZsNUIyczRpbDlhZ3RTVXFxUlU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K&#34;</span><span style="color:#bbb">
</span><span style="color:#bbb">  </span>nginx.key:<span style="color:#bbb"> </span><span style="color:#b44">&#34;LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2RhaURFZlZsZHdkbFIKd1V5eFpJWmVEZWNuTkFhbWh4d1NpeWF5N1AvOE9ta3NVQ3FCWmNpQ0RzZUh2dGtzbzlCSzhBZi9WemFhWm9zcApnZjYzUlZuZmNmVUlRQUN3WHhHVFhHMXJKVEVGSzhRSHA3VkpMcnpLUC9QOUxZcFlYTE0yYzZ3MmtjZUNmZitrCkU1bEVlNUJVbUNUV09UM3c4S1lPNzFLSWVuNEZJWTZMMDUrc2JGQmd1Z0ExUE5JdWFubm9UTWtlZTRuMG4rTDQKb3NCM01ZUDhtQmtRQlAzeE9JNHl3YjREZXUraURyU2pKSHJzQmlIT05Xc0RadXJFaXVJMmdoY1kxeWIyWHI2UAozVFVOcGNSbC9pVG9zQngxcHJHclk4V09HZVdPeGxZZmcvbWIvNnBuOUYvNWxlQlkrZStjSTlTMkQ0YXBKWUdpCkwxeHZzVWtGQWdNQkFBRUNnZ0VBZFhCK0xkbk8ySElOTGo5bWRsb25IUGlHWWVzZ294RGQwci9hQ1Zkank4dlEKTjIwL3FQWkUxek1yall6Ry9kVGhTMmMwc0QxaTBXSjdwR1lGb0xtdXlWTjltY0FXUTM5SjM0VHZaU2FFSWZWNgo5TE1jUHhNTmFsNjRLMFRVbUFQZytGam9QSFlhUUxLOERLOUtnNXNrSE5pOWNzMlY5ckd6VWlVZWtBL0RBUlBTClI3L2ZjUFBacDRuRWVBZmI3WTk1R1llb1p5V21SU3VKdlNyblBESGtUdW1vVlVWdkxMRHRzaG9reUxiTWVtN3oKMmJzVmpwSW1GTHJqbGtmQXlpNHg0WjJrV3YyMFRrdWtsZU1jaVlMbjk4QWxiRi9DSmRLM3QraTRoMTVlR2ZQegpoTnh3bk9QdlVTaDR2Q0o3c2Q5TmtEUGJvS2JneVVHOXBYamZhRGR2UVFLQmdRRFFLM01nUkhkQ1pKNVFqZWFKClFGdXF4cHdnNzhZTjQyL1NwenlUYmtGcVFoQWtyczJxWGx1MDZBRzhrZzIzQkswaHkzaE9zSGgxcXRVK3NHZVAKOWRERHBsUWV0ODZsY2FlR3hoc0V0L1R6cEdtNGFKSm5oNzVVaTVGZk9QTDhPTm1FZ3MxMVRhUldhNzZxelRyMgphRlpjQ2pWV1g0YnRSTHVwSkgrMjZnY0FhUUtCZ1FEQmxVSUUzTnNVOFBBZEYvL25sQVB5VWs1T3lDdWc3dmVyClUycXlrdXFzYnBkSi9hODViT1JhM05IVmpVM25uRGpHVHBWaE9JeXg5TEFrc2RwZEFjVmxvcG9HODhXYk9lMTAKMUdqbnkySmdDK3JVWUZiRGtpUGx1K09IYnRnOXFYcGJMSHBzUVpsMGhucDBYSFNYVm9CMUliQndnMGEyOFVadApCbFBtWmc2d1BRS0JnRHVIUVV2SDZHYTNDVUsxNFdmOFhIcFFnMU16M2VvWTBPQm5iSDRvZUZKZmcraEppSXlnCm9RN3hqWldVR3BIc3AyblRtcHErQWlSNzdyRVhsdlhtOElVU2FsbkNiRGlKY01Pc29RdFBZNS9NczJMRm5LQTQKaENmL0pWb2FtZm1nZEN0ZGtFMXNINE9MR2lJVHdEbTRpb0dWZGIwMllnbzFyb2htNUpLMUI3MkpBb0dBUW01UQpHNDhXOTVhL0w1eSt5dCsyZ3YvUHM2VnBvMjZlTzRNQ3lJazJVem9ZWE9IYnNkODJkaC8xT2sybGdHZlI2K3VuCnc1YytZUXRSTHlhQmd3MUtpbGhFZDBKTWU3cGpUSVpnQWJ0LzVPbnlDak9OVXN2aDJjS2lrQ1Z2dTZsZlBjNkQKckliT2ZIaHhxV0RZK2Q1TGN1YSt2NzJ0RkxhenJsSlBsRzlOZHhrQ2dZRUF5elIzT3UyMDNRVVV6bUlCRkwzZAp4Wm5XZ0JLSEo3TnNxcGFWb2RjL0d5aGVycjFDZzE2MmJaSjJDV2RsZkI0VEdtUjZZdmxTZEFOOFRwUWhFbUtKCnFBLzVzdHdxNWd0WGVLOVJmMWxXK29xNThRNTBxMmk1NVdUTThoSDZhTjlaMTltZ0FGdE5VdGNqQUx2dFYxdEYKWSs4WFJkSHJaRnBIWll2NWkwVW1VbGc9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K&#34;</span></code></pre></div>
<p>Now create the secrets using the file:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl create -f nginxsecrets.yaml
$ kubectl get secrets
NAME                  TYPE                                  DATA      AGE
default-token-il9rc   kubernetes.io/service-account-token   <span style="color:#666">1</span>         1d
nginxsecret           Opaque                                <span style="color:#666">2</span>         1m</code></pre></div>
<p>Now modify your nginx replicas to start an https server using the certificate in the secret, and the Service, to expose both ports (80 and 443):</p>

<table class="includecode" id="nginx-secure-app-yaml">
    <thead>
        <tr>
            <th>
                <a href="https://github.com/kubernetes/website/blob/master/content/en/docs/concepts/services-networking/nginx-secure-app.yaml" download="nginx-secure-app.yaml">
                    <code>nginx-secure-app.yaml docs/concepts/services-networking</code>
                </a>
                <img src="../../../../images/copycode.svg" style="max-height:24px" onclick="copyCode('nginx-secure-app-yaml')" title="Copy nginx-secure-app.yaml to clipboard">
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml">apiVersion:<span style="color:#bbb"> </span>v1<span style="color:#bbb">
</span><span style="color:#bbb"></span>kind:<span style="color:#bbb"> </span>Service<span style="color:#bbb">
</span><span style="color:#bbb"></span>metadata:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>name:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb">  </span>labels:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>run:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb"></span>spec:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>type:<span style="color:#bbb"> </span>NodePort<span style="color:#bbb">
</span><span style="color:#bbb">  </span>ports:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>-<span style="color:#bbb"> </span>port:<span style="color:#bbb"> </span><span style="color:#666">8080</span><span style="color:#bbb">
</span><span style="color:#bbb">    </span>targetPort:<span style="color:#bbb"> </span><span style="color:#666">80</span><span style="color:#bbb">
</span><span style="color:#bbb">    </span>protocol:<span style="color:#bbb"> </span>TCP<span style="color:#bbb">
</span><span style="color:#bbb">    </span>name:<span style="color:#bbb"> </span>http<span style="color:#bbb">
</span><span style="color:#bbb">  </span>-<span style="color:#bbb"> </span>port:<span style="color:#bbb"> </span><span style="color:#666">443</span><span style="color:#bbb">
</span><span style="color:#bbb">    </span>protocol:<span style="color:#bbb"> </span>TCP<span style="color:#bbb">
</span><span style="color:#bbb">    </span>name:<span style="color:#bbb"> </span>https<span style="color:#bbb">
</span><span style="color:#bbb">  </span>selector:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>run:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb"></span>---<span style="color:#bbb">
</span><span style="color:#bbb"></span>apiVersion:<span style="color:#bbb"> </span>apps/v1<span style="color:#bbb">
</span><span style="color:#bbb"></span>kind:<span style="color:#bbb"> </span>Deployment<span style="color:#bbb">
</span><span style="color:#bbb"></span>metadata:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>name:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb"></span>spec:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>selector:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>matchLabels:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>run:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb">  </span>replicas:<span style="color:#bbb"> </span><span style="color:#666">1</span><span style="color:#bbb">
</span><span style="color:#bbb">  </span>template:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>metadata:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>labels:<span style="color:#bbb">
</span><span style="color:#bbb">        </span>run:<span style="color:#bbb"> </span>my-nginx<span style="color:#bbb">
</span><span style="color:#bbb">    </span>spec:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>volumes:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>-<span style="color:#bbb"> </span>name:<span style="color:#bbb"> </span>secret-volume<span style="color:#bbb">
</span><span style="color:#bbb">        </span>secret:<span style="color:#bbb">
</span><span style="color:#bbb">          </span>secretName:<span style="color:#bbb"> </span>nginxsecret<span style="color:#bbb">
</span><span style="color:#bbb">      </span>containers:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>-<span style="color:#bbb"> </span>name:<span style="color:#bbb"> </span>nginxhttps<span style="color:#bbb">
</span><span style="color:#bbb">        </span>image:<span style="color:#bbb"> </span>bprashanth/nginxhttps:<span style="color:#666">1.0</span><span style="color:#bbb">
</span><span style="color:#bbb">        </span>ports:<span style="color:#bbb">
</span><span style="color:#bbb">        </span>-<span style="color:#bbb"> </span>containerPort:<span style="color:#bbb"> </span><span style="color:#666">443</span><span style="color:#bbb">
</span><span style="color:#bbb">        </span>-<span style="color:#bbb"> </span>containerPort:<span style="color:#bbb"> </span><span style="color:#666">80</span><span style="color:#bbb">
</span><span style="color:#bbb">        </span>volumeMounts:<span style="color:#bbb">
</span><span style="color:#bbb">        </span>-<span style="color:#bbb"> </span>mountPath:<span style="color:#bbb"> </span>/etc/nginx/ssl<span style="color:#bbb">
</span><span style="color:#bbb">          </span>name:<span style="color:#bbb"> </span>secret-volume<span style="color:#bbb">
</span><span style="color:#bbb"></span></code></pre></div>  </td>
        </tr>
    </tbody>
</table>

<p>Noteworthy points about the nginx-secure-app manifest:</p>

<ul>
<li>It contains both Deployment and Service specification in the same file.</li>
<li>The <a href="https://github.com/kubernetes/examples/tree/v1.11.3/staging/https-nginx/default.conf" target="_blank">nginx server</a> serves http traffic on port 80 and https traffic on 443, and nginx Service exposes both ports.</li>
<li>Each container has access to the keys through a volume mounted at /etc/nginx/ssl. This is setup <em>before</em> the nginx server is started.</li>
</ul>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml</code></pre></div>
<p>At this point you can reach the nginx server from any node.</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl get pods -o yaml | grep -i podip
    podIP: <span style="color:#666">10</span>.244.3.5
node $ curl -k https://10.244.3.5
...
&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</code></pre></div>
<p>Note how we supplied the <code>-k</code> parameter to curl in the last step, this is because we don&rsquo;t know anything about the pods running nginx at certificate generation time,
so we have to tell curl to ignore the CName mismatch. By creating a Service we linked the CName used in the certificate with the actual DNS name used by pods during Service lookup.
Let&rsquo;s test this from a pod (the same secret is being reused for simplicity, the pod only needs nginx.crt to access the Service):</p>

<table class="includecode" id="curlpod-yaml">
    <thead>
        <tr>
            <th>
                <a href="https://github.com/kubernetes/website/blob/master/content/en/docs/concepts/services-networking/curlpod.yaml" download="curlpod.yaml">
                    <code>curlpod.yaml docs/concepts/services-networking</code>
                </a>
                <img src="../../../../images/copycode.svg" style="max-height:24px" onclick="copyCode('curlpod-yaml')" title="Copy curlpod.yaml to clipboard">
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml">apiVersion:<span style="color:#bbb"> </span>apps/v1<span style="color:#bbb">
</span><span style="color:#bbb"></span>kind:<span style="color:#bbb"> </span>Deployment<span style="color:#bbb">
</span><span style="color:#bbb"></span>metadata:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>name:<span style="color:#bbb"> </span>curl-deployment<span style="color:#bbb">
</span><span style="color:#bbb"></span>spec:<span style="color:#bbb">
</span><span style="color:#bbb">  </span>selector:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>matchLabels:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>app:<span style="color:#bbb"> </span>curlpod<span style="color:#bbb">
</span><span style="color:#bbb">  </span>replicas:<span style="color:#bbb"> </span><span style="color:#666">1</span><span style="color:#bbb">
</span><span style="color:#bbb">  </span>template:<span style="color:#bbb">
</span><span style="color:#bbb">    </span>metadata:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>labels:<span style="color:#bbb">
</span><span style="color:#bbb">        </span>app:<span style="color:#bbb"> </span>curlpod<span style="color:#bbb">
</span><span style="color:#bbb">    </span>spec:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>volumes:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>-<span style="color:#bbb"> </span>name:<span style="color:#bbb"> </span>secret-volume<span style="color:#bbb">
</span><span style="color:#bbb">        </span>secret:<span style="color:#bbb">
</span><span style="color:#bbb">          </span>secretName:<span style="color:#bbb"> </span>nginxsecret<span style="color:#bbb">
</span><span style="color:#bbb">      </span>containers:<span style="color:#bbb">
</span><span style="color:#bbb">      </span>-<span style="color:#bbb"> </span>name:<span style="color:#bbb"> </span>curlpod<span style="color:#bbb">
</span><span style="color:#bbb">        </span>command:<span style="color:#bbb">
</span><span style="color:#bbb">        </span>-<span style="color:#bbb"> </span>sh<span style="color:#bbb">
</span><span style="color:#bbb">        </span>-<span style="color:#bbb"> </span>-c<span style="color:#bbb">
</span><span style="color:#bbb">        </span>-<span style="color:#bbb"> </span>while<span style="color:#bbb"> </span><span style="color:#a2f;font-weight:bold">true</span>;<span style="color:#bbb"> </span>do<span style="color:#bbb"> </span>sleep<span style="color:#bbb"> </span><span style="color:#666">1</span>;<span style="color:#bbb"> </span>done<span style="color:#bbb">
</span><span style="color:#bbb">        </span>image:<span style="color:#bbb"> </span>radial/busyboxplus:curl<span style="color:#bbb">
</span><span style="color:#bbb">        </span>volumeMounts:<span style="color:#bbb">
</span><span style="color:#bbb">        </span>-<span style="color:#bbb"> </span>mountPath:<span style="color:#bbb"> </span>/etc/nginx/ssl<span style="color:#bbb">
</span><span style="color:#bbb">          </span>name:<span style="color:#bbb"> </span>secret-volume<span style="color:#bbb">
</span><span style="color:#bbb"></span></code></pre></div>  </td>
        </tr>
    </tbody>
</table>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl create -f ./curlpod.yaml
$ kubectl get pods -l <span style="color:#b8860b">app</span><span style="color:#666">=</span>curlpod
NAME                               READY     STATUS    RESTARTS   AGE
curl-deployment-1515033274-1410r   <span style="color:#666">1</span>/1       Running   <span style="color:#666">0</span>          1m
$ kubectl <span style="color:#a2f">exec</span> curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/nginx.crt
...
&lt;title&gt;Welcome to nginx!&lt;/title&gt;
...</code></pre></div>
<h2 id="exposing-the-service">Exposing the Service</h2>

<p>For some parts of your applications you may want to expose a Service onto an external IP address. Kubernetes supports two ways of doing this: NodePorts and LoadBalancers. The Service created in the last section already used <code>NodePort</code>, so your nginx https replica is ready to serve traffic on the internet if your node has a public IP.</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl get svc my-nginx -o yaml | grep nodePort -C <span style="color:#666">5</span>
  uid: 07191fb3-f61a-11e5-8ae5-42010af00002
spec:
  clusterIP: <span style="color:#666">10</span>.0.162.149
  ports:
  - name: http
    nodePort: <span style="color:#666">31704</span>
    port: <span style="color:#666">8080</span>
    protocol: TCP
    targetPort: <span style="color:#666">80</span>
  - name: https
    nodePort: <span style="color:#666">32453</span>
    port: <span style="color:#666">443</span>
    protocol: TCP
    targetPort: <span style="color:#666">443</span>
  selector:
    run: my-nginx

$ kubectl get nodes -o yaml | grep ExternalIP -C <span style="color:#666">1</span>
    - address: <span style="color:#666">104</span>.197.41.11
      type: ExternalIP
    allocatable:
--
    - address: <span style="color:#666">23</span>.251.152.56
      type: ExternalIP
    allocatable:
...

$ curl https://&lt;EXTERNAL-IP&gt;:&lt;NODE-PORT&gt; -k
...
&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</code></pre></div>
<p>Let&rsquo;s now recreate the Service to use a cloud load balancer, just change the <code>Type</code> of <code>my-nginx</code> Service from <code>NodePort</code> to <code>LoadBalancer</code>:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl edit svc my-nginx
$ kubectl get svc my-nginx
NAME       CLUSTER-IP     EXTERNAL-IP        PORT<span style="color:#666">(</span>S<span style="color:#666">)</span>               AGE
my-nginx   <span style="color:#666">10</span>.0.162.149   <span style="color:#666">162</span>.222.184.144    <span style="color:#666">80</span>/TCP,81/TCP,82/TCP  21s

$ curl https://&lt;EXTERNAL-IP&gt; -k
...
&lt;title&gt;Welcome to nginx!&lt;/title&gt;</code></pre></div>
<p>The IP address in the <code>EXTERNAL-IP</code> column is the one that is available on the public internet.  The <code>CLUSTER-IP</code> is only available inside your
cluster/private cloud network.</p>

<p>Note that on AWS, type <code>LoadBalancer</code> creates an ELB, which uses a (long)
hostname, not an IP.  It&rsquo;s too long to fit in the standard <code>kubectl get svc</code>
output, in fact, so you&rsquo;ll need to do <code>kubectl describe service my-nginx</code> to
see it.  You&rsquo;ll see something like this:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ kubectl describe service my-nginx
...
LoadBalancer Ingress:   a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
...</code></pre></div>













<h2 id="what-s-next">What&#39;s next</h2>
<p>Kubernetes also supports Federated Services, which can span multiple
clusters and cloud providers, to provide increased availability,
better fault tolerance and greater scalability for your services. See
the <a href="../../cluster-administration/federation-service-discovery/index.html">Federated Services User Guide</a>
for further information.</p>






				<div class="issue-button-container">
					<p><a href="../connect-applications-service.1"><img src="https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/concepts/services-networking/connect-applications-service.md?pixel" alt="Analytics" /></a></p>
					
					
					<script type="text/javascript">
					PDRTJS_settings_8345992 = {
					"id" : "8345992",
					"unique_id" : "\/docs\/concepts\/services-networking\/connect-applications-service\/",
					"title" : "Connecting Applications with Services",
					"permalink" : "https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/connect-applications-service\/"
					};
					(function(d,c,j){if(!document.getElementById(j)){var pd=d.createElement(c),s;pd.id=j;pd.src=('https:'==document.location.protocol)?'https://polldaddy.com/js/rating/rating.js':'http://i0.poll.fm/js/rating/rating.js';s=document.getElementsByTagName(c)[0];s.parentNode.insertBefore(pd,s);}}(document,'script','pd-rating-js'));
					</script>
					<a href="../connect-applications-service.1" onclick="window.open('https://github.com/kubernetes/website/issues/new?title=Issue%20with%20' +
					'k8s.io'+window.location.pathname)" class="button issue">Create an Issue</a>
					
					
					
					<a href="../../../editdocs#docs/concepts/services-networking/connect-applications-service.md" class="button issue">Edit this Page</a>
					
				</div>
			</div>
		</section>
		<footer>
    <main class="light-text">
        <nav>
            
            
            
            <a href="../../../home.1">Documentation</a>
            
            <a href="../../../../blog/index.html">Blog</a>
            
            <a href="../../../../partners/index.html">Partners</a>
            
            <a href="../../../../community/index.html">Community</a>
            
            <a href="../../../../case-studies/index.html">Case Studies</a>
            
        </nav>
        <div class="social">
            <div>
                <a href="https://twitter.com/kubernetesio" class="twitter"><span>twitter</span></a>
                <a href="https://github.com/kubernetes/kubernetes" class="github"><span>Github</span></a>
                <a href="http://slack.k8s.io/" class="slack"><span>Slack</span></a>
            </div>
            <div>
                <a href="http://stackoverflow.com/questions/tagged/kubernetes" class="stack-overflow"><span>Stack Overflow</span></a>
                <a href="https://discuss.kubernetes.io" class="mailing-list"><span>Forum</span></a>
                <a href="https://calendar.google.com/calendar/embed?src=nt2tcnbtbied3l6gi2h29slvc0%40group.calendar.google.com" class="calendar"><span>Events Calendar</span></a>
            </div>
            <div>
                <a href="../../../getting-started-guides/index.html" class="button">Get Kubernetes</a>
                <a href="https://git.k8s.io/community/contributors/guide" class="button">Contribute</a>
            </div>
        </div>
        <div id="miceType" class="center">
            &copy; 2018 The Kubernetes Authors | Documentation Distributed under <a href="https://git.k8s.io/website/LICENSE" class="light-text">CC BY 4.0</a>
        </div>
        <div id="miceType" class="center">
            Copyright &copy; 2018 The Linux Foundation&reg;. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our <a href="https://www.linuxfoundation.org/trademark-usage" class="light-text">Trademark Usage page</a>
        </div>
    </main>
</footer>

		<button class="flyout-button" onclick="kub.toggleToc()"></button>

<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-36037335-10', 'auto');
ga('send', 'pageview');


(function () {
    window.addEventListener('DOMContentLoaded', init)

        
        function init() {
            window.removeEventListener('DOMContentLoaded', init)
                hideNav()
        }

    function hideNav(toc){
        if (!toc) toc = document.querySelector('#docsToc')
        if (!toc) return
            var container = toc.querySelector('.container')

                
                if (container) {
                    if (container.childElementCount === 0 || toc.querySelectorAll('a.item').length === 1) {
                        toc.style.display = 'none'
                            document.getElementById('docsContent').style.width = '100%'
                    }
                } else {
                    requestAnimationFrame(function () {
                        hideNav(toc)
                    })
                }
    }
})();
</script>



	</body>
</html>